//
// Created by 徐套 on 2023/9/19.
//



#include "server.h"


cloud_server::cloud_server(const char *str_ip, unsigned int u_port, int client, Clock_time *time0) {
    start = true;
    m_str_ip = str_ip;
    local_port_tcp = u_port;
    local_port_udp = u_port + 1;
    m_client_socket_tcp = client;
    time_right = time0;
    heart_num = 0;
    std::cout<<"create new car server："<<m_str_ip<<" ,port: "<<u_port<<std::endl;

}

cloud_server::~cloud_server() {
    start = false;
    if (m_client_socket_tcp) {
        close(m_client_socket_tcp);
    }
    if (m_client_socket_udp) {
        close(m_client_socket_udp);
    }
    std::cout << "free car connect" << std::endl;
}


bool cloud_server::init_server() {
    start = true;
    tcp_error_ = false;
    std::string init_udp_inf;
    init_udp_inf = "port:" + std::to_string(local_port_udp) + "!!";
    // 注意标识符
    char init_udp[1024];
    strcpy(init_udp, init_udp_inf.c_str());
    std::cout<<init_udp<<" 00 11 00"<<std::endl;
    send_msg_by_tcp(init_udp);
    char init_udp_inf_recv[1024];
    recv(m_client_socket_tcp, init_udp_inf_recv, 1024, 0);
    std::cout<<init_udp_inf_recv<<"get init"<<std::endl;
//    recv(m_client_socket_tcp, init_udp_inf_recv, 1024, 0);
//    std::cout<<init_udp_inf_recv<<"get init"<<std::endl;
    if (init_udp_inf_recv[0] == '!' && init_udp_inf_recv[1] == '?' && init_udp_inf_recv[2] == '!'){
        return true;
    } else
        return false;
}

void cloud_server::begin() {
    std::thread tcp_connect(&cloud_server::recv_msg_by_tcp, this);
    tcp_connect.detach();
    std::thread udp_connect(&cloud_server::recv_msg_by_udp, this);
    udp_connect.detach();
    std::thread heart_park(&cloud_server::heart_beat_time, this);
    heart_park.detach();

}

void cloud_server::recv_msg_by_tcp() {
    if (m_client_socket_tcp != -1){
        std::cout<<m_client_socket_tcp<<" begin tcp connect"<<std::endl;
        char read_msg[MAXRECV] = {0};
        std::string msg;
        while (start){
            memset(&read_msg, 0, sizeof(read_msg));
            recv(m_client_socket_tcp, read_msg, sizeof(read_msg), 0);
            // 信息处理
            if (read_msg[0] == '0' && read_msg[1] == ':') {
                // 心跳包处理
                heart_num = 0;
                msg = read_msg;
                time_out = time_right->get_now_time() - atoi(&msg[2]);

//                std::cout << "time out: " << time_out << std::endl;
                }
            else if (read_msg[0] == '2' && read_msg[1] == ':') {
                // 异常处理

            }
        }
    }
}

void cloud_server::recv_msg_by_udp() {
    m_client_socket_udp = socket(AF_INET, SOCK_DGRAM, 0);
    if (m_client_socket_udp != -1){
        std::cout<<m_client_socket_udp<<" begin udp connect"<<std::endl;

        sockaddr_in server_addr_;
        memset(&server_addr_, 0, sizeof(server_addr_));
        server_addr_.sin_family = AF_INET;
        server_addr_.sin_addr.s_addr = inet_addr(m_str_ip.c_str());
        server_addr_.sin_port = htons(local_port_udp);
        socklen_t server_len_ = sizeof(server_addr_);
        bind(m_client_socket_udp, (sockaddr *)&server_addr_, server_len_);
        memset(&client_addr_, 0, sizeof(client_addr_));
        client_len_ = sizeof(client_addr_);
        std::cout<<"udp,ip:"<<inet_ntoa(server_addr_.sin_addr)<<",port:"<<ntohs(server_addr_.sin_port)<<std::endl;
        CarState state;
        while (start){
                memset(&state, 0, sizeof(CarState));
                recvfrom(m_client_socket_udp, &state, sizeof (CarState), 0, (struct sockaddr*)&client_addr_, (socklen_t*)&client_len_);
                //处理信息
                if (state.car_name[0] == name_sign[2] && state.car_name[1] == name_sign[3] && state.car_name[2] == name_sign[4]){
                    std::cout<<state.car_name<<";"<<state.x<<";"<<state.y<<std::endl;
                    car_ = state;

                }
        }
    }
}

void cloud_server::heart_beat_time() {
    if (m_client_socket_tcp != -1){
        std::string time_log;
        char time_l[40];
        while (start){
            if (!tcp_error_) {
                time_log = "0:" + std::to_string(time_right->get_now_time()) + "!end!";
                strcpy(time_l, time_log.c_str());
//            std::cout<<"send msg:"<<time_l<<std::endl;
                send_msg_by_tcp(time_l);
                heart_num ++;
                std::this_thread::sleep_for(std::chrono::microseconds(1000));
                if (heart_num > MAXTIME) {
                    start = false;
                    tcp_error_ = true;
                }
            } else
                break;

        }
    }
}

bool cloud_server::send_msg_by_tcp(char* msg) {
    if (start && (!tcp_error_)){
        if (send(m_client_socket_tcp, msg, strlen(msg), 0) != -1) {
            return true;
        }
        else
            return true;
    } else
        return false;
}

void cloud_server::send_msg_by_udp(std::string &msg){
    if (start){
        char m[1024] = {0};
        strcpy(m, msg.c_str());
        sendto(m_client_socket_udp, m, sizeof(m), 0, (sockaddr*)&client_addr_, client_len_);
    }
}

unsigned int cloud_server::get_time_late() const {
    return time_out;
}

std::string cloud_server::get_name() const {
    return name_sign;
}

bool cloud_server::is_alive() const {
    if (!start)
        return false;
    if (tcp_error_)
        return false;
    return true;
}

CarState* cloud_server::get_now_state() {
    return &car_;
}